/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package entities.questionnaire;

import entities.utilisateur.Createur;
import entities.question.AbstractQuestion;
import entities.utilisateur.AbstractRepondant;
import entities.utilisateur.RepondantAuthentifie;
import entities.utilisateur.Valideur;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.rmi.CORBA.UtilDelegate;
import utils.UtilDate;

/**
 *
 * @author loic.vaugeois
 */
@Entity
@Table(name="questionnaire")
@NamedQueries({
@NamedQuery(name = "Questionnaire.findAllQuestionnaire", query
        = "SELECT q FROM Questionnaire q "
        + " ORDER BY q.dateCreation"),
@NamedQuery(name = "Questionnaire.findLastIdQuestionnaire", query
        = "SELECT max(q.id) FROM Questionnaire q "),
@NamedQuery(name = "Questionnaire.findQuestionnaireEnCreation", query 
        = "SELECT q FROM Questionnaire q "
        + " WHERE q.dateCreation IS NULL "
        + " AND q.dateValidation IS NULL "
        + " AND q.createur = :User"),
@NamedQuery(name = "Questionnaire.findQuestionnaireAValider", query
        = "SELECT q FROM Questionnaire q "
        + " WHERE q.dateCreation IS NOT NULL "
        + " AND q.dateValidation IS NULL "
        ),
@NamedQuery(name = "Questionnaire.findQuestionnaireDispoAuth", query
        = "SELECT q FROM Questionnaire q "
        + " WHERE q.dateCreation IS NOT NULL "
        + " AND q.dateValidation IS NOT NULL "
        + " AND q.dateDiffusion IS NOT NULL "
        + " AND q.dateDiffusion <= :now "
        + " AND ( q.dateCloture > :now "
        + " OR q.dateCloture IS NULL ) "
        + " AND ( q.id not in ( select r.questionnaire.id from AbstractReponse r where r.repondant = :User AND r.questionnaire.passageUnique = TRUE  ) ) "
        + " ORDER BY q.nom "
        ),
@NamedQuery(name = "Questionnaire.findQuestionnaireDispoNoAuth", query
        = "SELECT q FROM Questionnaire q "
        + " WHERE q.dateCreation IS NOT NULL "
        + " AND q.dateValidation IS NOT NULL "
        + " AND q.dateDiffusion IS NOT NULL "
        + " AND q.dateDiffusion <= :now "
        + " AND ( q.dateCloture > :now  "
        + " OR q.dateCloture IS NULL ) "
        + " AND q.typeQuestionnaire <> :TypeQuestionnaire "
        + " ORDER BY q.nom "
        ),
@NamedQuery(name = "Questionnaire.findQuestionnaireAPasser", query
        = "SELECT q FROM Questionnaire q "
        + " WHERE q.dateCreation IS NOT NULL "
        + " AND q.dateValidation <> :now "
        + " AND q.dateDiffusion = :now "
        + " AND ( q.dateCloture > :now  "
        + " OR q.dateCloture IS NULL ) "
        ),
@NamedQuery(name = "Questionnaire.findQuestionnaireADiffuser", query
        = "SELECT q FROM Questionnaire q "
        + " WHERE q.dateValidation IS NOT NULL "
        + " AND q.dateDiffusion = :now "
        + " AND ( q.dateCloture > :now  "
        + " OR q.dateCloture IS NULL ) "
        )
})
public class Questionnaire implements Serializable{

 /*
 *********************ATTRIBUTS
 */
    @Id
    @Column(name="id_questionnaire")
    private long id;

    /**
     * Apparence du Questionnaire (skin)
     */
    @ManyToOne(targetEntity=Apparence.class)
    @JoinColumn(name="id_apparence")
    private Apparence apparence;

    /**
     * Apparence du Questionnaire (skin)
     */
    @Column(name="duree_question")
    private int dureeQuestion;


    /**
     * Type du Questionnaire (Ouvert, fermé, mixte)
     */
    @Enumerated(EnumType.ORDINAL)
    @Column(name="type")
    private TypeQuestionnaire typeQuestionnaire;

    /**
     * Type de Scénario du questionnaire
     */
//    @ManyToOne(targetEntity=TypeScenario.class)
//    @JoinColumn(name="id_scenario")
    @Enumerated(EnumType.ORDINAL)
    @Column(name="id_scenario")
    private TypeScenario typeScenario;

    /**
     * Nom du Questionnaire
     */
    @Column(name="nom")
    private String nom;

    /**
     * Date de début création d'un questionnaire
     */
    @Temporal(TemporalType.DATE)
    @Column(name="date_creation")
    private Calendar dateCreation;

    /**
     * Date de début diffusion d'un questionnaire (peut-être null)
     */
    @Temporal(TemporalType.DATE)
    @Column(name="date_diffusion")
    private Calendar dateDiffusion;

    /**
     * Date d'échéance d'un questionnaire (peut-être NULL).
     */
    @Temporal(TemporalType.DATE)
    @Column(name="date_cloture")
    private Calendar dateCloture;

        /**
     * Date de validation d'un questionnaire (peut-être NULL).
     */
    @Temporal(TemporalType.DATE)
    @Column(name="date_validation")
    private Calendar dateValidation;

    /**
     * Créateur(rédacteur) d'un questionnaire
     */
    @ManyToOne(targetEntity=Valideur.class)
    @JoinColumn(name="id_valideur")
    private Valideur valideur;

     /**
     * Créateur(rédacteur) d'un questionnaire
     */
    @ManyToOne(targetEntity=Createur.class)
    @JoinColumn(name="id_createur")
    private Createur createur;

    /**
     * Liste des cibles d'un questionnaire Fermé ou Mixte (peut être NULL)
     */
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="diffuser",
    joinColumns={@JoinColumn(name="id_questionnaire")},
    inverseJoinColumns={@JoinColumn(name="id_utilisateur")})
    private List<RepondantAuthentifie> listCible;

    /**
     * Liste des questions du questionnaire
     * 
     */
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="demander",
    joinColumns={@JoinColumn(name="id_questionnaire")},
    inverseJoinColumns={@JoinColumn(name="id_question")})
    private List<AbstractQuestion> listQuestion ;


    /**
     * Booleen PassageUnique (Est ce qu'un utilisateur peux passer plusieurs fois un même questionnaire)
     */
    @Column(name="passage_unique")
    private boolean passageUnique;

    /**
     * Booleen QuestionnaireBloque (Le questionnaire est momentanement bloqué par l'administrateur)
     */
    @Column(name="bloque")
    private boolean questionnaireBloque;


 /*
 *********************GETTER SETTER
 */

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Apparence getApparence() {
        return apparence;
    }

    public void setApparence(Apparence apparence) {
        if (apparence==null) throw new IllegalArgumentException("L'apparence d'un questionnaire ne peut être null.");
        this.apparence = apparence;
    }

    public TypeQuestionnaire getTypeQuestionnaire() {
        return typeQuestionnaire;
    }

    public void setTypeQuestionnaire(TypeQuestionnaire typeQuestionnaire) {
        if (typeQuestionnaire==null) throw new IllegalArgumentException("Le type de questionnaire ne peut être null.");
        this.typeQuestionnaire = typeQuestionnaire;
    }

    public TypeScenario getTypeScenario() {
        return typeScenario;
    }

    public void setTypeScenario(TypeScenario typeScenario) {
        if (typeQuestionnaire==null) throw new IllegalArgumentException("Le type de scenario ne peut être null.");
        this.typeScenario = typeScenario;
    }

    public Calendar getDateCloture() {
        return dateCloture;
    }

    public Date getDateClotureDate() {
        return dateCloture.getTime();
    }

    public void setDateCloture(Calendar dateCloture) {
        if (dateCloture.before(UtilDate.getDateDuJourMin())) throw new IllegalArgumentException("La date de Cloture ne peut être antérieure à la date d'aujourd'hui.");
        this.dateCloture = dateCloture;
    }

    public void setDateClotureDate(Date dateCloture) {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(dateCloture);
        setDateCloture(gc);
    }

    public Calendar getDateCreation() {
        return dateCreation;
    }

    public void setDateCreation(Calendar dateCreation) {
        if (dateCreation==null) throw new IllegalArgumentException("La date de Creation ne peut être NULL.");
        if (dateCreation.before(UtilDate.getDateDuJourMin())) throw new IllegalArgumentException("La date de Creation ne peut être antérieure à la date d'aujourd'hui.");
        this.dateCreation = dateCreation;
    }

    public Calendar getDateDiffusion() {
        return dateDiffusion;
    }

    public Date getDateDiffusionDate() {
        return dateDiffusion.getTime();
    }

    public void setDateDiffusionDate(Date dateCloture) {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(dateCloture);
        setDateDiffusion(gc);
    }

    public void setDateDiffusion(Calendar dateDiffusion) {
        if (dateDiffusion.before(UtilDate.getDateDuJourMin())) throw new IllegalArgumentException("La date de Diffusion ne peut être antérieure à la date d'aujourd'hui.");
        this.dateDiffusion = dateDiffusion;
    }

    public String getNom() {
        return nom;
    }

    public void setNom(String nomQuestionnaire) {
        if (nomQuestionnaire==null) throw new IllegalArgumentException("Le nom du questionnaire ne peut être NULL.");
        if (nomQuestionnaire.isEmpty()) throw new IllegalArgumentException("Le nom du questionnaire ne peut être vide.");
        this.nom = nomQuestionnaire;
    }

    public Createur getCreateur() {
        return createur;
    }

    public void setCreateur(Createur createur) {
        if (createur==null) throw new IllegalArgumentException("Le createur ne peut être NULL.");
        this.createur = createur;
    }

    public Calendar getDateValidation() {
        return dateValidation;
    }

    public void setDateValidation(Calendar dateValidation) {
        if (dateValidation.before(UtilDate.getDateDuJourMin())) throw new IllegalArgumentException("La date de Validation ne peut être antérieure à la date d'aujourd'hui.");
        this.dateValidation = dateValidation;
    }

    public Valideur getValideur() {
        return valideur;
    }

    public void setValideur(Valideur valideur) {
        this.valideur = valideur;
    }

    public List<RepondantAuthentifie> getListCible() {
        return listCible;
    }

    public void setListCible(List<RepondantAuthentifie> listCible) {
        if (listCible.isEmpty()) Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "La liste de personnes ciblées par le questionnaire à été définie mais elle est vide.");
        this.listCible = listCible;
    }

    public List<AbstractQuestion> getListQuestion() {
        return listQuestion;
    }

    public void setListQuestion(List<AbstractQuestion> listQuestion) {
        if (listQuestion==null) throw new IllegalArgumentException("La liste de questions ne peut être NULL.");
        System.out.println(listQuestion.size());
        if (listQuestion.isEmpty()) throw new IllegalArgumentException("La liste de questions ne peut être vide.");
        this.listQuestion = listQuestion;
    }

    public Boolean getPassageUnique() {
        return passageUnique;
    }

    public void setPassageUnique(boolean passageUnique) {
       this.passageUnique = passageUnique;
    }

    public int getDureeQuestion() {
        return dureeQuestion;
    }

    public void setDureeQuestion(int dureeQuestion) {
        if (dureeQuestion<1) throw new IllegalArgumentException("La durée des question ne peut pas être <1.");
        this.dureeQuestion = dureeQuestion;
    }



    public Boolean getQuestionnaireBloque() {
        return questionnaireBloque;
    }

    public void setQuestionnaireBloque(boolean questionnaireBloque) {
        this.questionnaireBloque = questionnaireBloque;
    }

    public Boolean getIsValide() {
        if ((getDateValidation() != null) && (getDateValidation().before(UtilDate.getDateDuJourMax())))
            return true;
        return false;
    }

    public Boolean getIsDiffuse() {
        if ((getDateDiffusion() != null) && (getDateDiffusion().before(UtilDate.getDateDuJourMax())))
            return true;
        return false;
    }

    public Boolean getIsClos() {
        if ((getDateCloture() != null) && (getDateCloture().before(UtilDate.getDateDuJourMax())))
            return true;
        return false;
    }

//    public void addQuestion(AbstractQuestion uneQuestion){
//        this.getListQuestion().add(uneQuestion);
//    }
//
//    public void removeQuestion(AbstractQuestion uneQuestion){
//        this.ListQuestion.remove(uneQuestion);
//    }

/*
 ********************************************** CONSTRUCTEURS
 */

    /**
     * Constructeur Questionnaire
     * @param apparence
     * @param typeQuestionnaire
     * @param typeScenario
     * @param nomQuestionnaire
     * @param dateDiffusion
     * @param dateCloture
     * @param createur
     * @param ListCible
     * @param ListQuestion
     */
    public Questionnaire(Apparence apparence, int dureeQuestion, TypeQuestionnaire typeQuestionnaire, TypeScenario typeScenario, String nomQuestionnaire, Calendar dateDiffusion, Calendar dateCloture, Createur createur, List<RepondantAuthentifie> ListCible, List<AbstractQuestion> ListQuestion, boolean passageUnique) {
        setApparence(apparence);
        setDureeQuestion(dureeQuestion);
        setTypeQuestionnaire(typeQuestionnaire);
        setTypeScenario(typeScenario);
        setNom(nomQuestionnaire);
        setDateDiffusion(dateDiffusion);
        setDateCloture(dateCloture);
        setDateCreation(Calendar.getInstance());
        setCreateur(createur);
        setListCible(ListCible);
        setListQuestion(ListQuestion);
        setPassageUnique(passageUnique);
        setQuestionnaireBloque(Boolean.FALSE);
    }


    /**
     * Nécessaire à JPA
     */
    public Questionnaire(){
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Questionnaire other = (Questionnaire) obj;
        if (this.id != other.id) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + (int) (this.id ^ (this.id >>> 32));
        return hash;
    }

    @Override
    public String toString() {
        return getNom();
    }
        









    

}
